import { useCallback, useState } from "react";
import { IFormRef, createForm } from "../../lib";
import { IServiceApi, useService } from "../../lib/Service";
import nodeForge from "node-forge";
import Jsencrypt from "jsencrypt";
import lodash from "lodash";

interface IFormData {
    username: string;
    password: string;
    verifyCode: string;
}

interface ISubmitOption {
    publicKey: string;
    encrypt: boolean;
}

const encryptText = (data: string, publicKey: string) => {
    const publicKeyObj = nodeForge.pki.publicKeyFromPem(publicKey);
    const encryptedBytes = publicKeyObj.encrypt(data, "RSA-OAEP", {
        md: nodeForge.md.sha256.create(),
        mgf1: {
            md: nodeForge.md.sha1.create()
        }
    });
    return nodeForge.util.encode64(encryptedBytes);
};

export const loginForm = createForm({
    defaultValues: {
        username: "",
        password: "",
        verifyCode: ""
    }
});

export const useSubmit = (formRef: IFormRef<IFormData>, { publicKey, encrypt }: ISubmitOption) => {
    const service = useService();
    const [ myPublicKey, setMyPublicKey ] = useState<string|null>(publicKey);
    const getPublicKey = useCallback(() => {
        if(lodash.isEmpty(myPublicKey)) {
            return new Promise<{ publicKey?: string, message?: string }>((resolve, reject) => {
                return service.send({
                    endPoint: "login.config"
                }).then((resp: any) => {
                    const publicKeyValue = lodash.get(resp,"data.publicKey");
                    setMyPublicKey(publicKeyValue);
                    resolve({  publicKey: publicKeyValue });
                }).catch((err: any) => {
                    reject({ message: "获取公钥失败,请重试。", statusCode: 'NoConfig', error: err }); 
                });
            });
        } else {
            return Promise.resolve({ publicKey: myPublicKey });
        }
    }, [myPublicKey]);
    return useCallback(() => {
        return new Promise(async(resolve, reject) => {
            const { publicKey } = await getPublicKey();
            if(!publicKey || lodash.isEmpty(publicKey)) {
                reject({ message: "未获取到公钥", statusCode: 'NoConfig' } );
                return;
            }
            if(lodash.isEmpty(formRef.formData.username) || lodash.isEmpty(formRef.formData.password) || lodash.isEmpty(formRef.formData.verifyCode)) {
                reject({ message: "请输入账号密码", statusCode: 'NoInput' } );
                return;
            }
            const publicKeyVal = publicKey.replace(/\\n/g, "\n");
            let username = btoa(formRef.formData.username);
            let password = btoa(formRef.formData.password);
            if(encrypt) {
                username = encryptText(formRef.formData.username, publicKeyVal);
                password = encryptText(formRef.formData.password, publicKeyVal);
            }
            service.send({
                endPoint: "login.submit",
                data: {
                    ...formRef.formData,
                    username,
                    password
                }
            }).then((resp: any) => {
                sessionStorage.setItem("AdminData", JSON.stringify(resp.data));
                sessionStorage.setItem("loginState", "Login=" + resp.data.userName);
                resolve(resp);
            }).catch(reject);
        });
    }, [formRef, getPublicKey]);
};